/* USER CODE BEGIN Header */
/**
 ******************************************************************************
 * @file    adc.c
 * @brief   This file provides code for the configuration
 *          of the ADC instances.
 ******************************************************************************
 * @attention
 *
 * Copyright (c) 2024 STMicroelectronics.
 * All rights reserved.
 *
 * This software is licensed under terms that can be found in the LICENSE file
 * in the root directory of this software component.
 * If no LICENSE file comes with this software, it is provided AS-IS.
 *
 ******************************************************************************
 */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "adc.h"

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

ADC_HandleTypeDef hadc1;
ADC_HandleTypeDef hadc2;

/* ADC1 init function */
void MX_ADC1_Init(void)
{

  /* USER CODE BEGIN ADC1_Init 0 */

  /* USER CODE END ADC1_Init 0 */

  ADC_MultiModeTypeDef multimode = {0};
  ADC_InjectionConfTypeDef sConfigInjected = {0};

  /* USER CODE BEGIN ADC1_Init 1 */

  /* USER CODE END ADC1_Init 1 */
  //  hadc1.Instance = ADC1;                      // 使用ADC1外设
  //  hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE; // 禁用扫描模式（单通道）
  //  hadc1.Init.ContinuousConvMode = ENABLE;     // 启用连续转换模式
  //  hadc1.Init.DiscontinuousConvMode = DISABLE; // 禁用间断模式
  //  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; // 软件触发转换
  //  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;       // 数据右对齐
  //  hadc1.Init.NbrOfConversion = 1;                   // 1个转换通道
  //  if (HAL_ADC_Init(&hadc1) != HAL_OK)               // 初始化ADC1
  //  {
  //    Error_Handler();
  //  }
  /** Common config
   */
  hadc1.Instance = ADC1;
  hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc1.Init.ContinuousConvMode = ENABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 1;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure the ADC multi-mode
   */
  //  功能：配置ADC1与另一个ADC（如ADC2）协同工作。
  //
  //模式选择：
  //ADC_DUALMODE_INJECSIMULT 表示双ADC同步执行注入组转换（通常用于提高采样效率或同步采样多路信号）。
  multimode.Mode = ADC_DUALMODE_INJECSIMULT;
  if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Injected Channel
   */

  //  关键参数：
  //
  //触发源：T1_TRGO 表示由定时器1的触发信号（TRGO）启动注入组转换（适用于定时采样）。
  //
  //采样时间：7.5 个ADC时钟周期，影响转换精度（时间越长，抗噪性越好）。
  //
  //注入组：优先级高于常规通道，可中断常规转换（适合关键信号采样）。
  sConfigInjected.InjectedChannel = ADC_CHANNEL_0;
  sConfigInjected.InjectedRank = ADC_INJECTED_RANK_1;
  sConfigInjected.InjectedNbrOfConversion = 1;
  sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_7CYCLES_5;
  sConfigInjected.ExternalTrigInjecConv = ADC_EXTERNALTRIGINJECCONV_T1_TRGO;
  sConfigInjected.AutoInjectedConv = DISABLE;
  sConfigInjected.InjectedDiscontinuousConvMode = DISABLE;
  sConfigInjected.InjectedOffset = 0;
  if (HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC1_Init 2 */

  /* USER CODE END ADC1_Init 2 */
}
/* ADC2 init function */
void MX_ADC2_Init(void)
{

  /* USER CODE BEGIN ADC2_Init 0 */

  /* USER CODE END ADC2_Init 0 */

  ADC_InjectionConfTypeDef sConfigInjected = {0};

  /* USER CODE BEGIN ADC2_Init 1 */

  /* USER CODE END ADC2_Init 1 */

  /** Common config
   */
  hadc2.Instance = ADC2;
  hadc2.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc2.Init.ContinuousConvMode = ENABLE;
  hadc2.Init.DiscontinuousConvMode = DISABLE;
  hadc2.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc2.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc2.Init.NbrOfConversion = 1;
  if (HAL_ADC_Init(&hadc2) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Injected Channel
   */
  sConfigInjected.InjectedChannel = ADC_CHANNEL_1;
  sConfigInjected.InjectedRank = ADC_INJECTED_RANK_1;
  sConfigInjected.InjectedNbrOfConversion = 1;
  sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_7CYCLES_5;
  sConfigInjected.AutoInjectedConv = DISABLE;
  sConfigInjected.InjectedDiscontinuousConvMode = DISABLE;
  sConfigInjected.InjectedOffset = 0;
  if (HAL_ADCEx_InjectedConfigChannel(&hadc2, &sConfigInjected) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC2_Init 2 */

  /* USER CODE END ADC2_Init 2 */
}

void HAL_ADC_MspInit(ADC_HandleTypeDef *adcHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if (adcHandle->Instance == ADC1)
  {
    /* USER CODE BEGIN ADC1_MspInit 0 */

    /* USER CODE END ADC1_MspInit 0 */
    /* ADC1 clock enable */
    __HAL_RCC_ADC1_CLK_ENABLE();

    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**ADC1 GPIO Configuration
    PA0-WKUP     ------> ADC1_IN0
    */
    GPIO_InitStruct.Pin = GPIO_PIN_0;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* ADC1 interrupt Init */
    HAL_NVIC_SetPriority(ADC1_2_IRQn, 1, 0);
    HAL_NVIC_EnableIRQ(ADC1_2_IRQn);
    /* USER CODE BEGIN ADC1_MspInit 1 */

    /* USER CODE END ADC1_MspInit 1 */
  }
  else if (adcHandle->Instance == ADC2)
  {
    /* USER CODE BEGIN ADC2_MspInit 0 */

    /* USER CODE END ADC2_MspInit 0 */
    /* ADC2 clock enable */
    __HAL_RCC_ADC2_CLK_ENABLE();

    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**ADC2 GPIO Configuration
    PA1     ------> ADC2_IN1
    */
    GPIO_InitStruct.Pin = GPIO_PIN_1;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* ADC2 interrupt Init */
    HAL_NVIC_SetPriority(ADC1_2_IRQn, 1, 0);
    HAL_NVIC_EnableIRQ(ADC1_2_IRQn);
    /* USER CODE BEGIN ADC2_MspInit 1 */

    /* USER CODE END ADC2_MspInit 1 */
  }
}

void HAL_ADC_MspDeInit(ADC_HandleTypeDef *adcHandle)
{

  if (adcHandle->Instance == ADC1)
  {
    /* USER CODE BEGIN ADC1_MspDeInit 0 */

    /* USER CODE END ADC1_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_ADC1_CLK_DISABLE();

    /**ADC1 GPIO Configuration
    PA0-WKUP     ------> ADC1_IN0
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_0);

    /* ADC1 interrupt Deinit */
    /* USER CODE BEGIN ADC1:ADC1_2_IRQn disable */
    /**
     * Uncomment the line below to disable the "ADC1_2_IRQn" interrupt
     * Be aware, disabling shared interrupt may affect other IPs
     */
    /* HAL_NVIC_DisableIRQ(ADC1_2_IRQn); */
    /* USER CODE END ADC1:ADC1_2_IRQn disable */

    /* USER CODE BEGIN ADC1_MspDeInit 1 */

    /* USER CODE END ADC1_MspDeInit 1 */
  }
  else if (adcHandle->Instance == ADC2)
  {
    /* USER CODE BEGIN ADC2_MspDeInit 0 */

    /* USER CODE END ADC2_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_ADC2_CLK_DISABLE();

    /**ADC2 GPIO Configuration
    PA1     ------> ADC2_IN1
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1);

    /* ADC2 interrupt Deinit */
    /* USER CODE BEGIN ADC2:ADC1_2_IRQn disable */
    /**
     * Uncomment the line below to disable the "ADC1_2_IRQn" interrupt
     * Be aware, disabling shared interrupt may affect other IPs
     */
    /* HAL_NVIC_DisableIRQ(ADC1_2_IRQn); */
    /* USER CODE END ADC2:ADC1_2_IRQn disable */

    /* USER CODE BEGIN ADC2_MspDeInit 1 */

    /* USER CODE END ADC2_MspDeInit 1 */
  }
}

/* USER CODE BEGIN 1 */
#include "motor/motor_runtime_param.h"
#include "motor/foc.h"
#include "algorithm/filter.h"
#include "global_def.h"
#include "arm_math.h"
#include "usart.h"
#include <stdio.h>
void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef *hadc)
{
  if (hadc->Instance == ADC1)
  {
  //从 ADC1 和 ADC2 的注入通道 1 读取转换值，并将其转换为电压值 u_1 和 u_2。
  //HAL_ADCEx_InjectedGetValue 函数用于获取指定 ADC 实例和注入通道的转换值。
  //(1 << ADC_BITS) - 1 表示 ADC 的满量程值，其中 ADC_BITS 是 ADC 的分辨率位数。
  //ADC_REFERENCE_VOLT 是 ADC 的参考电压。
  //减去 0.5 可能是为了进行零点校准。

  //    1. (float)HAL_ADCEx_InjectedGetValue(&hadc1, ADC_INJECTED_RANK_1)
  //  HAL_ADCEx_InjectedGetValue 是 HAL 库提供的函数，用于获取指定 ADC 实例（这里是 hadc1）和注入通道（ADC_INJECTED_RANK_1）的转换结果，也就是 ADC 输出的数字值。
  //  (float) 是强制类型转换，将获取到的整数类型的数字值转换为浮点数类型，方便后续的浮点运算。

  //    2. (1 << ADC_BITS) - 1
  //  ADC_BITS 表示 ADC 的分辨率位数，比如常见的 12 位 ADC，ADC_BITS 就是 12。
  //  1 << ADC_BITS 是位运算，将数字 1 左移 ADC_BITS 位，得到的结果就是 ADC 的最大数字值加 1。例如 12 位 ADC，1 << 12 等于 4096。
  //  (1 << ADC_BITS) - 1 得到的就是 ADC 的最大数字值，12 位 ADC 的最大数字值就是 4095（范围是 0 - 4095）

  //    3. (float)HAL_ADCEx_InjectedGetValue(&hadc1, ADC_INJECTED_RANK_1) / ((1 << ADC_BITS) - 1)
  //    这一步是将 ADC 输出的数字值除以 ADC 的最大数字值，得到一个 0 到 1 之间的比例值，表示当前输入电压相对于 ADC 参考电压的比例。

  //    4. - 0.5
  //  减去 0.5 可能是为了进行零点校准。在某些应用场景中，ADC 的输入信号可能存在偏置，通过减去一个固定值可以将信号的零点调整到合适的位置。

  //    5. ADC_REFERENCE_VOLT * (...)
  //  ADC_REFERENCE_VOLT 是 ADC 的参考电压，也就是 ADC 能够测量的最大电压值。
  //  将前面得到的比例值乘以参考电压，就可以得到实际的模拟电压值。
    float u_1 = ADC_REFERENCE_VOLT * ((float)HAL_ADCEx_InjectedGetValue(&hadc1, ADC_INJECTED_RANK_1) / ((1 << ADC_BITS) - 1) - 0.5);
    float u_2 = ADC_REFERENCE_VOLT * ((float)HAL_ADCEx_InjectedGetValue(&hadc2, ADC_INJECTED_RANK_1) / ((1 << ADC_BITS) - 1) - 0.5);
		static int p_count=0;
		p_count ++;
		if(p_count%5000==0){
				printf("u_1 = %.3f\n", u_1);
				printf("u_2 = %.3f\n", u_2);
		}
		
  //    根据读取的电压值 u_1 和 u_2 计算电流值 i_1 和 i_2。
  // R_SHUNT 是分流电阻的阻值。
  // OP_GAIN 是运算放大器的增益。
    float i_1 = u_1 / R_SHUNT / OP_GAIN;
    float i_2 = u_2 / R_SHUNT / OP_GAIN;
    motor_i_u = i_1;
    motor_i_v = i_2;

  //    定义变量 i_alpha 和 i_beta，并调用 arm_clarke_f32 函数进行克拉克变换。
  //克拉克变换是将三相静止坐标系（abc 坐标系）下的电流转换为两相静止坐标系（αβ 坐标系）下的电流
    float i_alpha = 0;
    float i_beta = 0;
    arm_clarke_f32(motor_i_u, motor_i_v, &i_alpha, &i_beta);

  //    计算转子逻辑角度 rotor_logic_angle 的正弦值 sin_value 和余弦值 cos_value。
  //定义变量 _motor_i_d 和 _motor_i_q，并调用 arm_park_f32 函数进行帕克变换。
  //帕克变换是将两相静止坐标系（αβ 坐标系）下的电流转换为两相旋转坐标系（dq 坐标系）下的电流。
    float sin_value = arm_sin_f32(rotor_logic_angle);
    float cos_value = arm_cos_f32(rotor_logic_angle);
    float _motor_i_d = 0;
    float _motor_i_q = 0;
    arm_park_f32(i_alpha, i_beta, &_motor_i_d, &_motor_i_q, sin_value, cos_value);

  //    定义低通滤波器的系数 filter_alpha_i_d 和 filter_alpha_i_q。
  //调用 low_pass_filter 函数对 _motor_i_d 和 _motor_i_q 进行低通滤波处理，得到滤波后的电流值 motor_i_d 和 motor_i_q。
    float filter_alpha_i_d = 0.1;
    float filter_alpha_i_q = 0.1;
    motor_i_d = low_pass_filter(_motor_i_d, motor_i_d, filter_alpha_i_d);
    motor_i_q = low_pass_filter(_motor_i_q, motor_i_q, filter_alpha_i_q);

  //    根据 motor_control_context.type 的值，选择不同的电机控制模式。
  //control_type_position：位置控制模式，调用 lib_position_control 函数进行位置控制。
  //control_type_speed：速度控制模式，调用 lib_speed_control 函数进行速度控制。
  //control_type_torque：转矩控制模式，调用 lib_torque_control 函数进行转矩控制。
  //control_type_speed_torque：速度 - 转矩控制模式，调用 lib_speed_torque_control 函数进行速度 - 转矩控制。
  //control_type_position_speed_torque：位置 - 速度 - 转矩控制模式，调用 lib_position_speed_torque_control 函数进行位置 - 速度 - 转矩控制。
    switch (motor_control_context.type)
    {
    case control_type_position:
      lib_position_control(motor_control_context.position);
      break;
    case control_type_speed:
      lib_speed_control(motor_control_context.speed);
      break;
    case control_type_torque:
      lib_torque_control(motor_control_context.torque_norm_d, motor_control_context.torque_norm_q);
      break;
    case control_type_speed_torque:
      lib_speed_torque_control(motor_control_context.speed, motor_control_context.max_torque_norm);
      break;
    case control_type_position_speed_torque:
      lib_position_speed_torque_control(motor_control_context.position, motor_control_context.max_speed, motor_control_context.max_torque_norm);
      break;
    default:
      break;
    }
  }
}

/* USER CODE END 1 */
